package com.google.gwt.gfx.client;

import com.google.gwt.event.dom.client.MouseEvent;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;

/**
 * A type of {@link GwtEvent} for {@link DragTool} extension of a
 * {@link GFXPanel}.
 * 
 * @param <E>
 *            A type of {@link MouseEvent} that {@link DragEvent} wraps on
 */
public class DragEvent<E extends MouseEvent<?>> extends
		GwtEvent<DragEvent.Handler> {

	/**
	 * A type of {@link EventHandler} corresponding to a {@link DragEvent}.
	 */
	public interface Handler extends EventHandler {

		void onDrag(DragEvent<?> event);

	}

	/**
	 * Phase of dragging.
	 */
	public enum Type {
		/**
		 * Dragging begins. In this phase, offsets of dragging will reset.
		 */
		Begin,
		/**
		 * Dragging continues. In this phase, offsets of dragging updates.
		 */
		Continue,
		/**
		 * Dragging ends. In this phase, offsets of dragging will be used for a
		 * query of the viewer and then reset.
		 */
		End
	}

	/**
	 * Event type of this event.
	 */
	public static final GwtEvent.Type<DragEvent.Handler> TYPE = new GwtEvent.Type<DragEvent.Handler>();

	private int left = 0;

	private E mouseEvent = null;

	private int top = 0;

	private Type type = Type.Begin;

	/**
	 * @param type
	 *            {@link #getType()}
	 * @param left
	 *            {@link #getLeft()}
	 * @param top
	 *            {@link #getTop()}
	 * @param mouseEvent
	 *            {@link #getMouseEvent()}
	 */
	public DragEvent(Type type, int left, int top, E mouseEvent) {
		this.type = type;
		this.left = left;
		this.top = top;
		this.mouseEvent = mouseEvent;
	}

	@Override
	protected void dispatch(DragEvent.Handler handler) {
		handler.onDrag(this);
	}

	@Override
	public GwtEvent.Type<DragEvent.Handler> getAssociatedType() {
		return TYPE;
	}

	/**
	 * @return current position of mouse pointer from left side
	 */
	public int getLeft() {
		return left;
	}

	/**
	 * @return a mouse event this event wraps on
	 */
	public E getMouseEvent() {
		return mouseEvent;
	}

	/**
	 * @return current position of mouse pointer from top side
	 */
	public int getTop() {
		return top;
	}

	/**
	 * @return phase of the dragging
	 */
	public Type getType() {
		return type;
	}

}
